home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / zutil.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  22KB  |  998 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.    
  4. */
  5. #ifndef lint
  6. static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ir/RCS/zutil.c,v 1.6 92/03/26 18:27:16 jonathan Exp $";
  7. #endif
  8.  
  9. /* Change log:
  10.  * $Log:    zutil.c,v $
  11.  * Revision 1.6  92/03/26  18:27:16  jonathan
  12.  * Fixed function declaration.
  13.  * 
  14.  * Revision 1.5  92/03/07  19:41:14  jonathan
  15.  * ANSIfied argument list.
  16.  * 
  17.  * Revision 1.4  92/02/12  14:01:37  jonathan
  18.  * Added "$Log" so RCS will put the log message in the header
  19.  * 
  20.  *
  21.    3.26.90    Harry Morris, morris@think.com
  22.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  23.    4.11.90  HWM - fixed include file names, changed 
  24.                    - writeCompressedIntegerWithPadding() to
  25.                   writeCompressedIntWithPadding()
  26.                 - generalized conditional includes (see c-dialect.h)
  27.    3.7.91   Jonny Goldman.  Replaced "short" in makeBitMap with "int" line 632.
  28. */
  29.  
  30. #define _C_utils_Z39_50_
  31.  
  32. #include "zutil.h"
  33.  
  34. #include <math.h>
  35. #include <string.h>
  36.  
  37. char* readErrorPosition = NULL; /* pos where buf stoped making sense */
  38.  
  39. /*----------------------------------------------------------------------*/
  40. /* A note on error handling 
  41.    read - these are low level routines, they do not check the type tags
  42.    which (sometimes) preceed the data (this is done by the higher
  43.    level functions which call these functions).  There is no 
  44.    attempt made to check that the reading does not exceed the read
  45.    buffer.  Such cases should be very rare and usually will be 
  46.    caught by the calling functions. (note - it is unlikely that 
  47.    a series of low level reads will go far off the edge without
  48.    triggering a type error.  However, it is possible for a single
  49.    bad read in an array function (eg. readAny) to attempt to read a 
  50.    large ammount, possibly causing a segmentation violation or out
  51.    of memory condition.
  52.  */
  53. /*----------------------------------------------------------------------*/
  54.  
  55. diagnosticRecord* 
  56. makeDiag(surrogate,code,addInfo)
  57. boolean surrogate;
  58. char* code;
  59. char* addInfo;
  60. {
  61.   diagnosticRecord* diag = 
  62.     (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  63.   
  64.   diag->SURROGATE = surrogate;
  65.   memcpy(diag->DIAG,code,DIAGNOSTIC_CODE_SIZE);
  66.   diag->ADDINFO = s_strdup(addInfo); 
  67.  
  68.   return(diag);
  69. }
  70.  
  71. /*----------------------------------------------------------------------*/
  72.  
  73. void 
  74. freeDiag(diag)
  75. diagnosticRecord* diag;
  76.   if (diag != NULL)
  77.     { if (diag->ADDINFO != NULL)
  78.     s_free(diag->ADDINFO);
  79.     s_free(diag);
  80.       }
  81. }
  82.  
  83. /*----------------------------------------------------------------------*/
  84.  
  85. #define END_OF_RECORD    0x1D
  86.  
  87. char* 
  88. writeDiag(diag,buffer,len)
  89. diagnosticRecord* diag;
  90. char* buffer;
  91. long* len;
  92. /* diagnostics (as per Appendix D) have a very weird format - this changes
  93.    in SR-1
  94.  */
  95. {
  96.   char* buf = buffer;
  97.   long  length;
  98.   
  99.   if (diag == NULL)        /* handle unspecified optional args */
  100.     return(buf);
  101.  
  102.   buf = writeTag(DT_DatabaseDiagnosticRecords,buf,len);
  103.   CHECK_FOR_SPACE_LEFT(0L,len);
  104.   
  105.   length = 3; 
  106.   if (diag->ADDINFO != NULL)
  107.     length += strlen(diag->ADDINFO);
  108.     
  109.   if (length >= 0xFFFF )    /* make sure the length is reasonable */
  110.     { length = 0xFFFF - 1;
  111.       diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
  112.     }
  113.    
  114.   buf = writeBinaryInteger(length,2L,buf,len);
  115.  
  116.   CHECK_FOR_SPACE_LEFT(1L,len);
  117.   buf[0] = diag->DIAG[0]; 
  118.   buf++;
  119.   
  120.   CHECK_FOR_SPACE_LEFT(1L,len);
  121.   buf[0] = diag->DIAG[1];
  122.   buf++;
  123.   
  124.   if (length > 3)
  125.     { CHECK_FOR_SPACE_LEFT(3L,len);
  126.       memcpy(buf,diag->ADDINFO,(size_t)length - 3);
  127.       buf += length - 3;
  128.     }
  129.    
  130.   CHECK_FOR_SPACE_LEFT(1L,len);
  131.   buf[0] = diag->SURROGATE;
  132.   buf++;
  133.   
  134.   CHECK_FOR_SPACE_LEFT(1L,len);
  135.   buf[0] = END_OF_RECORD;
  136.   buf++;
  137.  
  138.   return(buf);
  139. }
  140.  
  141. /*----------------------------------------------------------------------*/
  142.  
  143. char* 
  144. readDiag(diag,buffer)
  145. diagnosticRecord** diag;
  146. char* buffer;
  147. {
  148.   char* buf = buffer;
  149.   diagnosticRecord* d 
  150.     = (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  151.   data_tag tag;
  152.   long len;
  153.   
  154.   buf = readTag(&tag,buf);
  155.   
  156.   buf = readBinaryInteger(&len,2L,buf);
  157.   
  158.   d->DIAG[0] = buf[0];
  159.   d->DIAG[1] = buf[1];
  160.   d->DIAG[2] = '\0';
  161.     
  162.   if (len > 3)
  163.     { d->ADDINFO = (char*)s_malloc((size_t)(len - 3 + 1));
  164.       memcpy(d->ADDINFO,(char*)(buf + 2),(size_t)(len - 3));
  165.       d->ADDINFO[len - 3] = '\0';
  166.     }
  167.   else
  168.     d->ADDINFO = NULL;
  169.     
  170.   d->SURROGATE = buf[len - 1];
  171.   
  172.   *diag = d;
  173.  
  174.   return(buf + len + 1);
  175. }
  176.  
  177. /*----------------------------------------------------------------------*/
  178.  
  179. #define continueBit    0x80
  180. #define dataMask    0x7F
  181. #define dataBits    7
  182.  
  183. char*
  184. writeCompressedInteger(num,buf,len)
  185. unsigned long num;
  186. char* buf;
  187. long* len;
  188. /* write a binary integer in the format described on p. 40.
  189.    this might be sped up 
  190. */
  191. {
  192.   char byte;
  193.   long i;
  194.   unsigned long size;
  195.   
  196.   size = writtenCompressedIntSize(num);
  197.   CHECK_FOR_SPACE_LEFT(size,len);
  198.   
  199.   for (i = size - 1; i >= 0; i--)
  200.     { byte = num & dataMask;
  201.       if (i != (size-1))    /* turn on continue bit */
  202.     byte = (char)(byte | continueBit);
  203.       buf[i] = byte;
  204.       num = num >> dataBits;    /* don't and here */
  205.     }
  206.    
  207.   return(buf + size);
  208.  
  209. /*----------------------------------------------------------------------*/
  210.  
  211. char*
  212. readCompressedInteger(num,buf)
  213. unsigned long *num;
  214. char* buf;
  215. /* read a binary integer in the format described on p. 40.
  216.    this might be sped up 
  217. */
  218. {
  219.   long i = 0;
  220.   unsigned char byte;
  221.  
  222.   *num = 0;
  223.   
  224.   do 
  225.     { byte = buf[i++];
  226.       *num = *num << dataBits;
  227.       *num += (byte & dataMask);
  228.     }
  229.   while (byte & continueBit);
  230.  
  231.   return(buf + i);
  232.  
  233. /*----------------------------------------------------------------------*/
  234.  
  235. #define pad    128 /* high bit is set */
  236.  
  237. char*
  238. writeCompressedIntWithPadding(num,size,buffer,len)
  239. unsigned long num;
  240. unsigned long size;
  241. char* buffer;
  242. long* len;
  243. /* Like writeCompressedInteger, except writes padding (128) to make
  244.    sure that size bytes are used.  This can be read correctly by 
  245.    readCompressedInteger()
  246. */
  247. {
  248.   char* buf = buffer;
  249.   unsigned long needed,padding;
  250.   long i;
  251.     
  252.   CHECK_FOR_SPACE_LEFT(size,len);
  253.   
  254.   needed = writtenCompressedIntSize(num);
  255.   padding = size - needed;
  256.   i = padding - 1;
  257.  
  258.   for (i = padding - 1;i >= 0;i--)
  259.     { buf[i] = pad;
  260.     }
  261.   
  262.   buf = writeCompressedInteger(num,buf + padding,len);
  263.   
  264.   return(buf);
  265.  
  266. /*----------------------------------------------------------------------*/
  267.  
  268. unsigned long
  269. writtenCompressedIntSize(num)
  270. unsigned long num;
  271. /* return the number of bytes needed to represnet the value num in
  272.    compressed format.  curently limited to 4 bytes
  273.  */
  274. {
  275.   if (num < CompressedInt1Byte) 
  276.     return(1);
  277.   else if (num < CompressedInt2Byte) 
  278.     return(2);
  279.   else if (num < CompressedInt3Byte)
  280.     return(3);
  281.   else
  282.     return(4);    
  283. }
  284.  
  285. /*----------------------------------------------------------------------*/
  286.  
  287. char*
  288. writeTag(tag,buf,len)
  289. data_tag tag;
  290. char* buf;
  291. long* len;
  292. /* write out a data tag */
  293.   return(writeCompressedInteger(tag,buf,len));
  294.  
  295. /*----------------------------------------------------------------------*/
  296.  
  297. char*
  298. readTag(tag,buf)
  299. data_tag* tag;
  300. char* buf;
  301. /* read a data tag */
  302.   return(readCompressedInteger(tag,buf));
  303.  
  304. /*----------------------------------------------------------------------*/
  305.  
  306. unsigned long 
  307. writtenTagSize(tag)
  308. data_tag tag;
  309.   return(writtenCompressedIntSize(tag));
  310. }
  311.  
  312. /*----------------------------------------------------------------------*/
  313.  
  314. data_tag
  315. peekTag(buf)
  316. char* buf;
  317. /* read a data tag without advancing the buffer */
  318. {
  319.   data_tag tag;
  320.   readTag(&tag,buf);
  321.   return(tag);
  322.  
  323. /*----------------------------------------------------------------------*/
  324.  
  325. any* 
  326. makeAny(size,data)
  327. unsigned long size;
  328. char* data;
  329. {
  330.   any* a = (any*)s_malloc((size_t)sizeof(any));
  331.   a->size = size;
  332.   a->bytes = data;
  333.   return(a);
  334. }
  335.  
  336. /*----------------------------------------------------------------------*/
  337.  
  338. void
  339. freeAny(a)
  340. any* a;
  341. /* destroy an any and its associated data. Assumes a->bytes was
  342.    allocated using the s_malloc family of libraries 
  343.  */
  344. {
  345.   if (a != NULL)
  346.     { if (a->bytes != NULL)
  347.     s_free(a->bytes);
  348.       s_free(a);
  349.     }
  350. }
  351.  
  352. /*----------------------------------------------------------------------*/
  353.  
  354. any* 
  355. duplicateAny(a)
  356. any* a;
  357. {
  358.   any* copy = NULL;
  359.  
  360.   if (a == NULL)
  361.     return(NULL);
  362.  
  363.   copy = (any*)s_malloc((size_t)sizeof(any));
  364.   copy->size = a->size;
  365.   if (a->bytes == NULL)
  366.     copy->bytes = NULL;
  367.   else
  368.     { copy->bytes = (char*)s_malloc((size_t)copy->size);
  369.       memcpy(copy->bytes,a->bytes,(size_t)copy->size);
  370.     }
  371.   return(copy);
  372. }
  373.  
  374. /*----------------------------------------------------------------------*/
  375.  
  376. char* 
  377. writeAny(a,tag,buffer,len)
  378. any* a;
  379. data_tag tag;
  380. char* buffer;
  381. long* len;
  382. /* write an any + tag and size info */
  383. {
  384.   char* buf = buffer;
  385.  
  386.   if (a == NULL)        /* handle unspecified optional args */
  387.     return(buf);
  388.   
  389.   /* write the tags */
  390.   buf = writeTag(tag,buf,len);
  391.   buf = writeCompressedInteger(a->size,buf,len);
  392.  
  393.   /* write the bytes */
  394.   CHECK_FOR_SPACE_LEFT(a->size,len);
  395.   memcpy(buf,a->bytes,(size_t)a->size);
  396.  
  397.   return(buf+a->size);
  398. }
  399.  
  400. /*----------------------------------------------------------------------*/
  401.  
  402. char* 
  403. readAny(anAny,buffer)
  404. any** anAny;
  405. char* buffer;
  406. /* read an any + tag and size info */
  407. {
  408.   char* buf = buffer;
  409.   any* a = (any*)s_malloc((size_t)sizeof(any));
  410.   data_tag tag;
  411.   
  412.   buf = readTag(&tag,buf);
  413.   buf = readCompressedInteger(&a->size,buf);
  414.   /* now simply copy the bytes */
  415.   a->bytes = (char*)s_malloc((size_t)a->size);
  416.   memcpy(a->bytes,buf,(size_t)a->size);
  417.   *anAny = a;
  418.   return(buf+a->size);
  419. }
  420.  
  421. /*----------------------------------------------------------------------*/
  422.  
  423. unsigned long 
  424. writtenAnySize(tag,a)
  425. data_tag tag;
  426. any* a;
  427. {
  428.   unsigned long size;
  429.  
  430.   if (a == NULL)
  431.     return(0);
  432.  
  433.   size = writtenTagSize(tag);
  434.   size += writtenCompressedIntSize(a->size);
  435.   size += a->size;
  436.   return(size);
  437. }
  438.  
  439. /*----------------------------------------------------------------------*/
  440.  
  441. any*
  442. stringToAny(s)
  443. char* s;
  444. {
  445.   any* a = NULL;
  446.   
  447.   if (s == NULL)
  448.     return(NULL);
  449.     
  450.   a = (any*)s_malloc((size_t)sizeof(any));
  451.   a->size = strlen(s);
  452.   a->bytes = (char*)s_malloc((size_t)a->size);
  453.   memcpy(a->bytes,s,(size_t)a->size);
  454.   return(a);
  455. }
  456.  
  457. /*----------------------------------------------------------------------*/
  458.  
  459. char*
  460. anyToString(a)
  461. any* a;
  462. {
  463.   char* s = NULL;
  464.   
  465.   if (a == NULL)
  466.     return(NULL);
  467.     
  468.   s = s_malloc((size_t)(a->size + 1));
  469.   memcpy(s,a->bytes,(size_t)a->size);
  470.   s[a->size] = '\0';
  471.   return(s);
  472. }
  473.  
  474. /*----------------------------------------------------------------------*/
  475.  
  476. char* 
  477. writeString(s,tag,buffer,len)
  478. char* s;
  479. data_tag tag;
  480. char* buffer;
  481. long* len;
  482. /* Write a C style string.  The terminating null is not written. 
  483.    This function is not part of the Z39.50 spec.  It is provided
  484.    for the convienience of those wishing to pass C strings in 
  485.    the place of an any.
  486.  */
  487. {
  488.   char* buf = buffer;
  489.   any* data = NULL;
  490.   if (s == NULL)
  491.     return(buffer);        /* handle unused optional item before making an any */
  492.   data = (any*)s_malloc((size_t)sizeof(any)); 
  493.   data->size = strlen(s);
  494.   data->bytes = s;        /* save a copy here by not using stringToAny() */
  495.   buf = writeAny(data,tag,buf,len);
  496.   s_free(data);            /* don't use freeAny() since it will free s too */
  497.   return(buf);
  498. }
  499.  
  500. /*----------------------------------------------------------------------*/
  501.  
  502. char* 
  503. readString(s ,buffer)
  504. char** s ;
  505. char* buffer;
  506. /* Read an any and convert it into a C style string.
  507.    This function is not part of the Z39.50 spec.  It is provided
  508.    for the convienience of those wishing to pass C strings in 
  509.    the place of an any. 
  510.  */
  511. {
  512.   any* data = NULL;
  513.   char* buf = readAny(&data,buffer);
  514.   *s = anyToString(data);
  515.   freeAny(data);
  516.   return(buf);
  517. }
  518.  
  519. /*----------------------------------------------------------------------*/
  520.  
  521. unsigned long 
  522. writtenStringSize(tag,s)
  523. data_tag tag;
  524. char* s;
  525. {
  526.   unsigned long size;
  527.  
  528.   if (s == NULL)
  529.    return(0);
  530.  
  531.   size = writtenTagSize(tag);
  532.   size += writtenCompressedIntSize(size);
  533.   size += strlen(s);
  534.   return(size);
  535. }
  536.  
  537. /*----------------------------------------------------------------------*/
  538.  
  539. any* 
  540. longToAny(num)
  541. long num;
  542. /* a convienience function */
  543. {
  544.   char s[40];
  545.  
  546.   sprintf(s,"%ld",num);
  547.   
  548.   return(stringToAny(s));
  549. }
  550.  
  551. /*----------------------------------------------------------------------*/
  552.  
  553. long
  554. anyToLong(a)
  555. any* a;
  556. /* a convienience function */
  557. {
  558.   long num;
  559.   char* str = NULL;
  560.   str = anyToString(a);
  561.   sscanf(str,"%ld",&num);    /* could check the result and return
  562.                    an error */
  563.   s_free(str);
  564.   return(num);
  565. }
  566.  
  567. /*----------------------------------------------------------------------*/
  568.  
  569. #define bitsPerByte    8
  570.  
  571. #ifdef ANSI_LIKE /* use ansi */
  572.  
  573. bit_map*
  574. makeBitMap(unsigned long numBits,...)
  575. /* construct and return a bitmap with numBits elements */
  576. {
  577.   va_list ap;
  578.   long i,j;
  579.   bit_map* bm = NULL;
  580.  
  581.   va_start(ap,numBits);
  582.   
  583.   bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  584.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte); 
  585.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  586.   
  587.   /* fill up the bits */
  588.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  589.     { char byte = 0;
  590.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  591.     { if ((i * bitsPerByte + j) < numBits)
  592.         { boolean bit = false;
  593.           bit = (boolean)va_arg(ap,boolean); 
  594.           if (bit)
  595.             { byte = byte | (1 << (bitsPerByte - j - 1));
  596.             }
  597.         }
  598.       }
  599.       bm->bytes[i] = byte;
  600.     }
  601.  
  602.   va_end(ap);
  603.   return(bm);
  604. }
  605.  
  606. #else /* use K & R */
  607.  
  608. bit_map*
  609. makeBitMap(va_alist)
  610. va_dcl
  611. /* construct and return a bitmap with numBits elements */
  612. {
  613.   va_list ap;
  614.   long i,j;
  615.   unsigned long numBits;
  616.   bit_map* bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  617.  
  618.   va_start(ap);
  619.   
  620.   numBits = va_arg(ap,unsigned long);
  621.  
  622.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte);
  623.   
  624.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  625.   
  626.   /* fill up the bits */
  627.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  628.     { char byte = 0;
  629.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  630.     { if ((i * bitsPerByte + j) < numBits)
  631.         { boolean bit;
  632.           bit = (boolean)va_arg(ap,int); /* really boolean, but this 
  633.                         is how it is passed on stack */
  634.           if (bit)
  635.             { byte = byte | (1 << (bitsPerByte - j - 1));
  636.             }
  637.         }
  638.       }
  639.       bm->bytes[i] = byte;
  640.     }
  641.  
  642.   va_end(ap);
  643.  
  644.   return(bm);
  645. }
  646.  
  647. #endif 
  648.  
  649. /*----------------------------------------------------------------------*/
  650.  
  651. void
  652. freeBitMap(bm)
  653. bit_map* bm;
  654. /* destroy a bit map created by makeBitMap() */
  655. {
  656.   s_free(bm->bytes);
  657.   s_free(bm);
  658. }
  659.  
  660. /*----------------------------------------------------------------------*/
  661.  
  662. /* use this routine to interpret a bit map.  pos specifies the bit 
  663.    number.  bit 0 is the Leftmost bit of the first byte.  
  664.    Could do bounds checking.
  665.  */
  666.  
  667. boolean
  668. bitAtPos(pos,bm)
  669. long pos;
  670. bit_map* bm;
  671. {
  672.   if (pos > bm->size*bitsPerByte)
  673.     return false;
  674.   else
  675.     return((bm->bytes[(pos / bitsPerByte)] & 
  676.         (0x80>>(pos % bitsPerByte))) ?
  677.        true : false);
  678. }
  679.  
  680. /*----------------------------------------------------------------------*/
  681.  
  682. char*
  683. writeBitMap(bm,tag,buffer,len)
  684. bit_map* bm;
  685. data_tag tag;
  686. char* buffer;
  687. long* len;
  688. /* write a bitmap + type and size info */
  689.   return(writeAny((any*)bm,tag,buffer,len));
  690. }
  691.  
  692. /*----------------------------------------------------------------------*/
  693.  
  694. char*
  695. readBitMap(bm,buffer)
  696. bit_map** bm;
  697. char* buffer;
  698. /* read a bitmap + type and size info */
  699.   return(readAny((any**)bm,buffer));
  700. }
  701.  
  702. /*----------------------------------------------------------------------*/
  703.  
  704. char* 
  705. writeByte(byte,buf,len)
  706. unsigned long byte;
  707. char* buf;
  708. long* len;
  709. {
  710.   CHECK_FOR_SPACE_LEFT(1L,len);
  711.   buf[0] = byte & 0xFF; /* we really only want the first byte */
  712.   return(buf + 1);
  713. }
  714.  
  715. /*----------------------------------------------------------------------*/
  716.  
  717. char* 
  718. readByte(byte,buf)
  719. unsigned char* byte;
  720. char* buf;
  721. {
  722.   *byte = buf[0];
  723.   return(buf + 1);
  724. }
  725.  
  726. /*----------------------------------------------------------------------*/
  727.  
  728. char* 
  729. writeBoolean(flag,buf,len)
  730. boolean flag;
  731. char* buf;
  732. long* len;
  733. {
  734.   return(writeByte(flag,buf,len));
  735. }
  736.  
  737. /*----------------------------------------------------------------------*/
  738.  
  739. char* 
  740. readBoolean(flag,buffer)
  741. boolean* flag;
  742. char* buffer;
  743. {
  744.   unsigned char byte;
  745.   char* buf = readByte(&byte,buffer);
  746.   *flag = (byte == true) ? true : false;
  747.   return(buf);
  748. }
  749.  
  750. /*----------------------------------------------------------------------*/
  751.  
  752. char*
  753. writePDUType(pduType,buf,len)
  754. pdu_type pduType;
  755. char* buf;
  756. long* len;
  757. /* PDUType is a single byte */
  758. {
  759.   return(writeBinaryInteger((long)pduType,(unsigned long)1,buf,len));
  760.  
  761. /*----------------------------------------------------------------------*/
  762.  
  763. char*
  764. readPDUType(pduType,buf)
  765. pdu_type* pduType;
  766. char* buf;
  767. /* PDUType is a single byte */
  768. {
  769.   return(readBinaryInteger((long*)pduType,(unsigned long)1,buf));
  770.  
  771. /*----------------------------------------------------------------------*/
  772.  
  773. pdu_type
  774. peekPDUType(buf)
  775. char* buf;
  776. /* read the next pdu without advancing the buffer, Note that this 
  777.    function is to be used on a buffer that is known to contain an
  778.    APDU.  The pdu_type is written HEADER_LEN bytes into the buffer
  779.  */
  780. {
  781.   pdu_type pdu;
  782.   readPDUType(&pdu,buf + HEADER_LEN);
  783.   return(pdu);
  784. }
  785.  
  786. /*----------------------------------------------------------------------*/
  787.  
  788. #define BINARY_INTEGER_BYTES    sizeof(long) /* the number of bytes used by
  789.                         a "binary integer" */
  790. char*
  791. writeBinaryInteger(num,size,buf,len)
  792. long num;
  793. unsigned long size;
  794. char* buf;
  795. long* len;
  796. /* write out first size bytes of num - no type info
  797.   XXX should this take unsigned longs instead ???  */
  798. {
  799.   long i;
  800.   char byte;
  801.  
  802.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  803.     return(NULL);        /* error */
  804.  
  805.   CHECK_FOR_SPACE_LEFT(size,len);
  806.  
  807.   for (i = size - 1; i >= 0; i--)
  808.     { byte = (char)(num & 255);
  809.       buf[i] = byte;
  810.       num = num >> bitsPerByte; /* don't and here */
  811.     }
  812.  
  813.   return(buf + size);
  814. }
  815.  
  816. /*----------------------------------------------------------------------*/
  817.  
  818. char*
  819. readBinaryInteger(num,size,buf)
  820. long* num;
  821. unsigned long size;
  822. char* buf;
  823. /* read in first size bytes of num - no type info
  824.   XXX this should take unsigned longs instead !!! */
  825. {
  826.   long i;
  827.   unsigned char byte;
  828.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  829.     return(buf);        /* error */
  830.   *num = 0;
  831.   for (i = 0; i < size; i++)
  832.     { byte = buf[i];
  833.       *num = *num << bitsPerByte;
  834.       *num += byte;
  835.     }
  836.   return(buf + size);
  837. }
  838.  
  839. /*----------------------------------------------------------------------*/
  840.  
  841. unsigned long 
  842. writtenCompressedBinIntSize(num)
  843. long num;
  844. /* return the number of bytes needed to represent the value num.
  845.    currently limited to max of 4 bytes 
  846.    Only compresses for positive nums - negatives get whole 4 bytes
  847.  */
  848. {
  849.   if (num < 0L)
  850.     return(4);
  851.   else if (num < 256L)        /* 2**8 */
  852.     return(1);
  853.   else if (num < 65536L)    /* 2**16 */
  854.     return(2);
  855.   else if (num < 16777216L)    /* 2**24 */
  856.     return(3);
  857.   else
  858.     return(4);
  859. }
  860.  
  861. /*----------------------------------------------------------------------*/
  862.  
  863. char*
  864. writeNum(num,tag,buffer,len)
  865. long num;
  866. data_tag tag;
  867. char* buffer;
  868. long* len;
  869. /* write a binary integer + size and tag info */
  870. {
  871.   char* buf = buffer;
  872.   long size = writtenCompressedBinIntSize(num);
  873.   
  874.   if (num == UNUSED)
  875.     return(buffer);
  876.     
  877.   buf = writeTag(tag,buf,len);
  878.   buf = writeCompressedInteger(size,buf,len); 
  879.   buf = writeBinaryInteger(num,(unsigned long)size,buf,len); 
  880.   return(buf);
  881. }
  882.  
  883. /*----------------------------------------------------------------------*/
  884.  
  885. char*
  886. readNum(num,buffer)
  887. long* num;
  888. char* buffer;
  889. /* read a binary integer + size and tag info */
  890. {
  891.   char* buf = buffer;
  892.   data_tag tag;
  893.   unsigned long size;
  894.   unsigned long val;
  895.   
  896.   buf = readTag(&tag,buf);
  897.   buf = readCompressedInteger(&val,buf);
  898.   size = (unsigned long)val;
  899.   buf = readBinaryInteger(num,size,buf);
  900.   return(buf);
  901. }
  902.  
  903. /*----------------------------------------------------------------------*/
  904.  
  905. unsigned long 
  906. writtenNumSize(tag,num)
  907. data_tag tag;
  908. long num;
  909. {
  910.   long dataSize = writtenCompressedBinIntSize(num);
  911.   long size;
  912.   
  913.   size = writtenTagSize(tag); /* space for the tag */
  914.   size += writtenCompressedIntSize(dataSize); /* space for the size */
  915.   size += dataSize; /* space for the data */
  916.   
  917.   return(size);
  918. }
  919.  
  920. /*----------------------------------------------------------------------*/
  921.  
  922. typedef void (voidfunc)();
  923.  
  924. void
  925. doList(list,func)
  926. void** list;
  927. voidfunc *func;
  928. /* call func on each element of the NULL terminated list of pointers */
  929. {
  930.   register long i;
  931.   register void* ptr = NULL;
  932.   if (list == NULL)
  933.     return;
  934.   for (i = 0,ptr = list[i]; ptr != NULL; ptr = list[++i])
  935.     (*func)(ptr);
  936. }
  937.  
  938. /*----------------------------------------------------------------------*/
  939.  
  940. char* 
  941. writeProtocolVersion(buf,len)
  942. char* buf;
  943. long* len;
  944. /* write a bitmap describing the protocols available */
  945. {
  946.   static bit_map* version = NULL;
  947.  
  948.   if (version == NULL)
  949.    { version = makeBitMap((unsigned long)1,true); /* version 1! */
  950.    }
  951.     
  952.   return(writeBitMap(version,DT_ProtocolVersion,buf,len));
  953. }
  954.  
  955. /*----------------------------------------------------------------------*/
  956.  
  957. char*
  958. defaultImplementationID()
  959. {
  960.   static char    ImplementationID[] = "TMC";
  961.   return(ImplementationID);
  962. }
  963.  
  964. /*----------------------------------------------------------------------*/
  965.  
  966. char*
  967. defaultImplementationName()
  968. {
  969.   static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
  970.   return(ImplementationName);
  971. }
  972.  
  973. /*----------------------------------------------------------------------*/
  974.  
  975. char*
  976. defaultImplementationVersion()
  977. {
  978.   static char    ImplementationVersion[] = "2.0A";
  979.   return(ImplementationVersion);
  980. }
  981.  
  982. /*----------------------------------------------------------------------*/
  983.  
  984.